//SPDX-FileCopyrightText: Copyright 2022-2024 深圳市同心圆网络有限公司
//SPDX-License-Identifier: GPL-3.0-only

package dataview_dao

import (
	"context"

	"atomgit.com/openlinksaas-org/api-server/dao/db_ns"
	"atomgit.com/openlinksaas-org/proto-gen-go.git/project_dataview_api"
	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/mongo"
	"go.mongodb.org/mongo-driver/mongo/options"
)

type ViewInfoDbItem struct {
	ViewId                string   `bson:"_id"`
	ProjectId             string   `bson:"projectId"`
	Title                 string   `bson:"title"`
	BgColor               string   `bson:"bgColor"`
	Desc                  string   `bson:"desc"`
	OwnerUserId           string   `bson:"ownerUserId"`
	CreateTime            int64    `bson:"createTime"`
	ExtraUpdateUserIdList []string `bson:"extraUpdateUserIdList"`
}

func (item *ViewInfoDbItem) ToViewInfo() *project_dataview_api.ViewInfo {
	if item.ExtraUpdateUserIdList == nil {
		item.ExtraUpdateUserIdList = []string{}
	}
	return &project_dataview_api.ViewInfo{
		ViewId:                item.ViewId,
		ProjectId:             item.ProjectId,
		Title:                 item.Title,
		BgColor:               item.BgColor,
		Desc:                  item.Desc,
		OwnerUserId:           item.OwnerUserId,
		CreateTime:            item.CreateTime,
		ExtraUpdateUserIdList: item.ExtraUpdateUserIdList,
	}
}

type _ViewDao struct {
	mc *mongo.Collection
}

func newViewDao(db *mongo.Database) (*_ViewDao, error) {
	mc := db.Collection(db_ns.DB_NS_PROJECT_DATAVIEW + "view")
	_, err := mc.Indexes().CreateOne(context.Background(), mongo.IndexModel{
		Keys: bson.D{{"projectId", 1}, {"createTime", 1}},
	})
	if err != nil {
		return nil, err
	}
	return &_ViewDao{mc: mc}, nil
}

func (db *_ViewDao) Insert(ctx context.Context, dbItem *ViewInfoDbItem) error {
	_, err := db.mc.InsertOne(ctx, dbItem)
	return err
}

func (db *_ViewDao) Exist(ctx context.Context, projectId, viewId string) (bool, error) {
	count, err := db.mc.CountDocuments(ctx, bson.M{"projectId": projectId, "_id": viewId})
	return count > 0, err
}

func (db *_ViewDao) Get(ctx context.Context, projectId, viewId string) (*ViewInfoDbItem, error) {
	retItem := &ViewInfoDbItem{}
	err := db.mc.FindOne(ctx, bson.M{"projectId": projectId, "_id": viewId}).Decode(retItem)
	return retItem, err
}

func (db *_ViewDao) Remove(ctx context.Context, projectId, viewId string) error {
	_, err := db.mc.DeleteOne(ctx, bson.M{"projectId": projectId, "_id": viewId})
	return err
}

func (db *_ViewDao) Count(ctx context.Context, projectIdList []string) (uint32, error) {
	if len(projectIdList) == 0 {
		return 0, nil
	}
	count, err := db.mc.CountDocuments(ctx, bson.M{"projectId": bson.M{"$in": projectIdList}})
	return uint32(count), err
}

func (db *_ViewDao) List(ctx context.Context, projectIdList []string, offset, limit int64) ([]*ViewInfoDbItem, error) {
	if len(projectIdList) == 0 {
		return []*ViewInfoDbItem{}, nil
	}
	cursor, err := db.mc.Find(ctx, bson.M{"projectId": bson.M{"$in": projectIdList}},
		options.Find().SetSkip(offset).SetLimit(limit).SetSort(bson.M{"createTime": -1}))
	if err != nil {
		return nil, err
	}
	retList := []*ViewInfoDbItem{}
	err = cursor.All(ctx, &retList)
	return retList, err
}

func (db *_ViewDao) Update(ctx context.Context, projectId, viewId, title, bgColor, desc string) error {
	_, err := db.mc.UpdateOne(ctx, bson.M{"projectId": projectId, "_id": viewId},
		bson.M{"$set": bson.M{
			"title":   title,
			"bgColor": bgColor,
			"desc":    desc,
		}})
	return err
}

func (db *_ViewDao) UpdateExtraUpdateUserIdList(ctx context.Context, projectId, viewId string, userIdList []string) error {
	_, err := db.mc.UpdateOne(ctx, bson.M{"projectId": projectId, "_id": viewId},
		bson.M{"$set": bson.M{
			"extraUpdateUserIdList": userIdList,
		}})
	return err
}
